package com.pokemon.psyduckgateway.filter.security;

import cloud.pokemon.commoncore.code.CodeMsg;
import cloud.pokemon.commoncore.context.TokenContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;

/**
 * 自定义认证过滤器
 */
@Component
public class PreGlobalCustomFilter implements GlobalFilter, Ordered {

    @Value("${auth.skip.urls}")
    private String[] skipAuthUrls;

    @Value("${auth.header.authName}")
    private String AuthName;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();


    private boolean isSkipUrl(String url) {
        for (String skipAuthUrl : skipAuthUrls) {
            if (antPathMatcher.match(skipAuthUrl, url)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String uri = request.getURI().getPath();
        Map<String, List<String>> headers = request.getHeaders();
        if (!headers.isEmpty()) {
            //保证上下文一致性
            TokenContext.setHaedersLocal(headers);
        }

        //无需验证的url（/login）等
        if (isSkipUrl(uri)) {
            return chainFilterExchange(exchange, chain);
        }

        //拦截全局认证
        List<String> token = headers.get(AuthName);
        if (token == null || token.isEmpty()) {
            //证明没有去Author服务认证token，直接返回认证失败
            return monoResponse(response, CodeMsg.unAuthorized);
        } else {
            //已经带了token的情况，需要验证是否正确，是否需要过期续签
            return chainFilterVerifyToken(exchange, chain);
        }
    }

    private Mono<Void> chainFilterVerifyToken(ServerWebExchange exchange, GatewayFilterChain chain) {

        //认证失败操作

        //成功放行操作
        return chain.filter(exchange);
    }

    private Mono<Void> monoResponse(ServerHttpResponse response, String unAuthorized) {
        //未认证，直接返回
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        DataBuffer dataBuffer = response.bufferFactory().allocateBuffer();
        return response.writeWith(Flux.just(dataBuffer));
    }

    private Mono<Void> chainFilterExchange(ServerWebExchange exchange, GatewayFilterChain chain) {
        //成功放行操作
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 此处使用-100 和 Spring Security Filter 的顺序对齐
        return -100;
    }
}
